home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
vr386
/
int3d.asm
< prev
next >
Wrap
Assembly Source File
|
1994-01-10
|
12KB
|
652 lines
TITLE INT3D - OBJECT/MOVE SPPT IN ASSEMBLER
COMMENT $
/* Routines for moving, scaling and rotating objects */
/* Matrix math, assembly by Dave Stampe */
/* converted to assembly 12/12/93 by Dave Stampe */
ALL routines in this module by Dave Stampe
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
$
.MODEL large
; # define XFSC 536870912 /* 2**29 for shifting xform coeffs to long */
.DATA
include 3dstruct.inc
extrn _sqrtable ; pointer to 8-bit precision sqrt table
.CODE INTMATH
MULT29 MACRO a,b ; multiply <3.29> -> eax
mov eax,DWORD PTR a
imul DWORD PTR b
shrd eax,edx,29
adc eax,0
ENDM
MMULT29 MACRO a,b,c ; multiply 3 of <3.29> -> eax
mov eax,DWORD PTR a
imul DWORD PTR b
shrd eax,edx,29
adc eax,0
imul DWORD PTR c
shrd eax,edx,29
adc eax,0
ENDM
DOTPROD MACRO a,b,c,x,y,z,p ; dot product plus p, accum in ecx:ebx
mov eax,a ; result in eax
imul DWORD PTR x
mov ecx,edx
mov ebx,eax
mov eax,b
imul DWORD PTR y
add ebx,eax
adc ecx,edx
mov eax,c
imul DWORD PTR z
add eax,ebx
adc edx,ecx
shrd eax,edx,29
adc eax,p
ENDM
;/************ COLLISION DETECTION AND SELECTION ***********/
;long sphere_pretest(OBJECT *obj, long x, long y, long z)
; tests 3D selection point for best object to select */
; returns 0x7FFFFFFF if not in obj bounds, else
; returns abs(x1-x2) + abs(y1-y2) + abs(z1-z2)
; <conservative closeness: always greater than actual>
obj equ [bp+8] ; arguments
x equ [bp+12]
y equ [bp+16]
z equ [bp+20]
sx equ es:[di].O_sphx
sy equ es:[di].O_sphy
sz equ es:[di].O_sphz
sr equ es:[di].O_sphr
PUBLIC _sphere_pretest
_sphere_pretest proc far
.386
push ebp
mov ebp,esp
push ecx
push edi
les di,DWORD PTR obj ; ptr to object
mov eax,sx ;/* x bounds */
sub eax,x
cmp eax,sr
jg notin
neg eax
cmp eax,sr
jg notin
mov eax,sy ;/* y bounds */
sub eax,y
cmp eax,sr
jg notin
neg eax
cmp eax,sr
jg notin
mov eax,sz ;/* z bounds */
sub eax,z
cmp eax,sr
jg notin
neg eax
cmp eax,sr
jg notin
imul eax ;/* square of distance to center */
mov ebx,eax
mov ecx,edx
mov eax,sx
sub eax,x
imul eax
add ebx,eax
adc ecx,edx
mov eax,sy
sub eax,y
imul eax
add ebx,eax
adc ecx,edx
mov eax,sr ;/* square of radius */
imul eax
cmp edx,ecx
ja in
jb notin
cmp eax,ebx
jae in
notin: ;/* outside of sphere */
mov eax,07FFFFFFFh; ;/* big never wins */
jmp retlarge
in:
;test ebx,-1 ;/* shift so denom. is 32-bit or less */
;jz nolo1
;mov eax,edx
;xor edx,edx
;mov ebx,ecx
;xor ecx,ecx
;nolo1:
mov eax,x ;/* abs(x-sx)+abs(y-sy)+abs(z-sz) approx. dist from center */
sub eax,sx
cdq
xor eax,edx
sub eax,edx
mov ebx,eax
mov eax,y
sub eax,sy
cdq
xor eax,edx
sub eax,edx
add ebx,eax
mov eax,z
sub eax,sz
cdq
xor eax,edx
sub eax,edx
add ebx,eax
mov eax,ebx
retlarge:
shld edx,eax,16 ; return in eax and dx:ax
pop edi
pop ecx
mov esp,ebp
pop ebp
ret
_sphere_pretest endp
;/************* POLYGON NORMAL COMPUTATION *************/
; /* compute, unitize (3.29 format) normal to plane. */
; /* returns -1 if normal is zero, else log2(length) */
;int find_normal(long x1, long y1, long z1,
; long x2, long y2, long z2,
; long x3, long y3, long z3,
; long *xn, long *yn, long *zn)
; extern int sqrtable[1024];
x1 equ [bp+8] ; arguments
y1 equ [bp+12]
z1 equ [bp+16]
x2 equ [bp+20]
y2 equ [bp+24]
z2 equ [bp+28]
x3 equ [bp+32]
y3 equ [bp+36]
z3 equ [bp+40]
xn equ [bp+44]
yn equ [bp+48]
zn equ [bp+52]
xh equ [bp-4] ; locals
xl equ [bp-8]
yh equ [bp-12]
yl equ [bp-16]
zh equ [bp-20]
zl equ [bp-24]
xah equ [bp-28]
xal equ [bp-32]
yah equ [bp-36]
yal equ [bp-40]
zah equ [bp-44]
zal equ [bp-48]
length equ [bp-52]
PUBLIC _find_normal
_find_normal proc far
.386
push ebp
mov ebp,esp
sub esp,60
push esi
push edi
push ecx
push edx
mov eax,y2 ;/* compute 64-bit cross product */
sub eax,y1 ;/* and also abs. value for shifts */
mov ecx,z3
sub ecx,z2
imul ecx
mov edi,edx
mov esi,eax
mov eax,y3
sub eax,y2
mov ecx,z2
sub ecx,z1
imul ecx
sub esi,eax
sbb edi,edx
mov xh,edi
mov xl,esi
jge stax
not edi
not esi
add esi,1
adc edi,0
stax:
mov xah,edi
mov xal,esi
mov eax,z2
sub eax,z1
mov ecx,x3
sub ecx,x2
imul ecx
mov edi,edx
mov esi,eax
mov eax,z3
sub eax,z2
mov ecx,x2
sub ecx,x1
imul ecx
sub esi,eax
sbb edi,edx
mov yh,edi
mov yl,esi
jge stay
not edi
not esi
add esi,1
adc edi,0
stay:
mov yah,edi
mov yal,esi
mov eax,x2
sub eax,x1
mov ecx,y3
sub ecx,y2
imul ecx
mov edi,edx
mov esi,eax
mov eax,x3
sub eax,x2
mov ecx,y2
sub ecx,y1
imul ecx
sub esi,eax
sbb edi,edx
mov zh,edi
mov zl,esi
jge staz
not edi
not esi
add esi,1
adc edi,0
staz:
mov zah,edi
mov zal,esi
;/* now normalize to 3.29 */
or esi,yal
or esi,xal
or edi,yah
or edi,xah
jz zero_h
xor ax,ax ;/* ax is shift count */
test edi,0FFFF0000h ;/* top word not zero: cnvt to 1.n <3.29> */
jz z16h
add ax,16
shr edi,16
z16h:
test di,0FF00h
jz z8h
add ax,8
shr edi,8
z8h:
shl edi,8 ;/* most ecomonical pos'n */
bsr cx,di ;/* get exact shift */
sub cx,5
add cx,ax
mov eax,xh ;/* convert cross product to 1.n */
shrd xl,eax,cl
mov eax,yh
shrd yl,eax,cl
mov eax,zh
shrd zl,eax,cl
add cx,29
mov length,cx
jmp dshnorm
zero_h:
or esi,esi
jz zero_normal
mov ax,24
test esi,0FFFF0000h ;/* top word is zero: cnvt to 1.n <3.29> */
jz z16l
sub ax,16
shr esi,16
z16l:
test si,0FF00h
jz z8l
sub ax,8
shr esi,8
z8l:
shl esi,8 ;/* most ecomonical pos'n */
bsr cx,si ;/* get exact shift */
neg cx
add cx,13
add cx,ax
jz noshiftl
jg lshiftl
neg cx
mov eax,xh ;/* convert cross product to 1.n */
shrd xl,eax,cl ;/* need ext. for borderline cases */
mov eax,yh
shrd yl,eax,cl
mov eax,zh
shrd zl,eax,cl
noshiftl:
add cx,29
mov length,cx
jmp dshnorm
lshiftl:
shl DWORD PTR xl,cl
shl DWORD PTR yl,cl
shl DWORD PTR zl,cl
mov ax,29
sub ax,cx
mov length,ax
dshnorm:
jmp finish
zero_normal:
mov eax,1 ; *xn = *yn = *zn = -1
mov xn,eax
mov yn,eax
mov zn,eax
mov WORD PTR length,0 ; return 0
jmp rtn_result
finish: ;/* compute magnitude, convert to unit length */
mov eax,xl ;/* compute squares */
sar eax,16
imul ax
mov bx,dx
mov cx,ax
mov eax,yl
sar eax,16
imul ax
add cx,ax
adc bx,dx
mov eax,zl
sar eax,16
imul ax
add cx,ax
adc bx,dx
shr bx,4 ;/* magnitude << 13 */
shl bx,1
les si,DWORD PTR _sqrtable
mov cx,WORD PTR es:[bx+si]
movzx ecx,cx
mov eax,xl ;/* scale cross product */
cdq
shld edx,eax,13
shl eax,13
idiv ecx
mov xl,eax
mov eax,yl
cdq
shld edx,eax,13
shl eax,13
idiv ecx
mov yl,eax
mov eax,zl
cdq
shld edx,eax,13
shl eax,13
idiv ecx
mov zl,eax
rtn_result: ; /* left-hand coordinate system: negate normal */
les bx,DWORD PTR xn
mov eax,xl
neg eax
mov DWORD PTR es:[bx],eax
les bx,DWORD PTR yn
mov eax,yl
neg eax
mov DWORD PTR es:[bx],eax
les bx,DWORD PTR zn
mov eax,zl
neg eax
mov DWORD PTR es:[bx],eax
mov ax, length
pop edx
pop ecx
pop edi
pop esi
mov esp,ebp
pop ebp
ret
_find_normal endp
;/******************** APPLY MATRIX TO OBJECTS **************/
;void matmove_osphere(OBJECT *obj, MATRIX m)
obj equ [bp+8] ; arguments
m equ [bp+12]
PUBLIC _matmove_osphere
_matmove_osphere proc far
.386
push ebp
mov ebp,esp
push ds
push esi
push edi
push ecx
push edx
lds si,DWORD PTR m ; PTR TO MATRIX
les di,DWORD PTR obj ; ptr to object
inc DWORD PTR es:[bx].O_ucount ; mark as moved
DOTPROD ds:[si],ds:[si+4],ds:[si+8],es:[di].O_osphx,es:[di].O_osphy,es:[di].O_osphz,ds:[si+36]
mov es:[di].O_sphx,eax
DOTPROD ds:[si+12],ds:[si+16],ds:[si+20],es:[di].O_osphx,es:[di].O_osphy,es:[di].O_osphz,ds:[si+40]
mov es:[di].O_sphy,eax
DOTPROD ds:[si+24],ds:[si+28],ds:[si+32],es:[di].O_osphx,es:[di].O_osphy,es:[di].O_osphz,ds:[si+44]
mov es:[di].O_sphz,eax
pop edx
pop ecx
pop edi
pop esi
pop ds
mov esp,ebp
pop ebp
ret
_matmove_osphere endp
;void matmove_rep(REP *rep, MATRIX m)
rep equ [bp+8] ; arguments
m equ [bp+12]
i equ [bp-4] ; locals
v equ [bp-8]
p equ [bp-12]
vc equ [bp-14]
pc equ [bp-16]
vs equ SIZE VERTEX ; structure sizes
ps equ SIZE POLY
PUBLIC _matmove_rep
_matmove_rep proc far
.386
push ebp
mov ebp,esp
sub esp,20
push ds
push esi
push edi
push ecx
push edx
lds si,DWORD PTR m ; PTR TO MATRIX
les di,DWORD PTR rep ; ptr to rep
mov eax, es:[di].R_verts ; get data
mov v, eax
mov eax, es:[di].R_polys
mov p, eax
mov ax, es:[di].R_nverts
mov vc, ax
mov ax, es:[di].R_npolys
mov pc, ax
les di,DWORD PTR v ;/* rotate/translate all vertices */
vconv:
DOTPROD ds:[si],ds:[si+4],ds:[si+8],es:[di].V_ox,es:[di].V_oy,es:[di].V_oz,ds:[si+36]
mov es:[di].V_x,eax
DOTPROD ds:[si+12],ds:[si+16],ds:[si+20],es:[di].V_ox,es:[di].V_oy,es:[di].V_oz,ds:[si+40]
mov es:[di].V_y,eax
DOTPROD ds:[si+24],ds:[si+28],ds:[si+32],es:[di].V_ox,es:[di].V_oy,es:[di].V_oz,ds:[si+44]
mov es:[di].V_z,eax
add di,vs
dec WORD PTR vc
jnz vconv
les di,DWORD PTR p ; now for polys: rotate all normals */
pconv:
DOTPROD ds:[si],ds:[si+4],ds:[si+8],es:[di].P_onormx,es:[di].P_onormy,es:[di].P_onormz,0
mov es:[di].P_normx,eax
DOTPROD ds:[si+12],ds:[si+16],ds:[si+20],es:[di].P_onormx,es:[di].P_onormy,es:[di].P_onormz,0
mov es:[di].P_normy,eax
DOTPROD ds:[si+24],ds:[si+28],ds:[si+32],es:[di].P_onormx,es:[di].P_onormy,es:[di].P_onormz,0
mov es:[di].P_normz,eax
add di,ps
dec WORD PTR pc
jnz pconv
pop edx
pop ecx
pop edi
pop esi
pop ds
mov esp,ebp
pop ebp
ret
_matmove_rep endp
end